04_A_TSDecomposition

References

  1. Hyndman, R.J., & Athanasopoulos, G., 2021. Forecasting: principles and practice. 3rd edition.
  2. Kourentzes, Nikolaus. Additive and multiplicative seasonality - can you identify them correctly? Link

Packages

library(fpp3)
── Attaching packages ────────────────────────────────────────────── fpp3 0.5 ──
✔ tibble      3.2.1     ✔ tsibble     1.1.3
✔ dplyr       1.1.2     ✔ tsibbledata 0.4.1
✔ tidyr       1.3.0     ✔ feasts      0.3.1
✔ lubridate   1.9.2     ✔ fable       0.3.3
✔ ggplot2     3.4.3     ✔ fabletools  0.3.3
── Conflicts ───────────────────────────────────────────────── fpp3_conflicts ──
✖ lubridate::date()    masks base::date()
✖ dplyr::filter()      masks stats::filter()
✖ tsibble::intersect() masks base::intersect()
✖ tsibble::interval()  masks lubridate::interval()
✖ dplyr::lag()         masks stats::lag()
✖ tsibble::setdiff()   masks base::setdiff()
✖ tsibble::union()     masks base::union()

Additive vs. Multiplicative decomposition

A time series might be decomposed, in general terms, in three different components:

  • A seasonal component \(S_t\)

  • A trend-cycle component \(T_t\)

    • Some authors separate the trend and cycle component. Here we consider trend-cycle because the usual decomposition algorithms extract them together, not separately.
  • The remainder component \(R_t\)

Typically we distinguish between two types of decomposition schemes:

  • An additive scheme: the variation around the trend-cycle of the seasonal pattern does NOT vary with the level of the time series (with the trend component value).
\[\begin{align*} y_t = S_t + T_t + R_t \end{align*}\]
  • A multiplicative scheme: the variation around the trend-cycle of the seasonal pattern appears to be proportional to the level of the time series (to the value of the trend component).
\[\begin{align*} y_t = S_t\times{T_t}\times{R_t} \end{align*}\]
  • In this case, the logarithmic transformation is commonly used. This renders a purely multiplicative scheme additive:
\[\begin{align*} log{y_t}= \log{S_t} + \log{T_t} + \log{R_t} \end{align*}\]

Example 1 - Additive scheme

We will work with the number of persons employed in retail in the US as shown in Figure 3.5. We can see the monthly number of persons in thousands employed in the retail sector across the US since 1990:

us_retail_employment <- us_employment %>%
  filter(year(Month) >= 1990, Title == "Retail Trade") %>%
  select(-Series_ID)
autoplot(us_retail_employment, Employed) +
  labs(y = "Persons (thousands)",
       title = "Total employment in US retail")

With this code we can obtain the components using STL decomposition (more on that later in the chapter, donot worry too much about the code now):

dcmp_components <- 
  
  us_retail_employment %>%
  
  # 1. Define and fit the decomposition model
  model(stl = STL(Employed)) %>%
  
  # 2. Extracts the components out of the model. Note that the function
  # components is not applicable to every type of model. It is applicable to
  # decomposition models and ETS models (later in the subject).
  components(dcmp)
dcmp_components %>%
  
  # 1. Format dataframe to tsibble
  as_tsibble() %>%
  
  # 2. Plot the decomposition using ggplot
  autoplot(Employed, colour="gray") +
  geom_line(aes(y=trend), colour = "#D55E00") +
  labs(
    y = "Persons (thousands)",
    title = "Total employment in US retail"
  )

Using autoplot, we can have a look at all the components at once

dcmp_components %>% autoplot()

Example 2 - Multiplicative scheme:

Let us resort again to the monthly medicare Australian prescription data, because it shows a clear multiplicative scheme:

a10 <- 
  # 1. Dataframe containing monthly medicare expenses per type of drug
  PBS %>%
  
  # 2. Filter for antidiabetic drigs
  filter(ATC2 == "A10") %>%
  
  # 3. select subset of columns
  select(Month, Concession, Type, Cost) %>%
  
  # 4. Add the total expenditure per month
  index_by(Month) %>% 
  summarise(TotalC = sum(Cost)) %>%
  
  # 5. Scale to millions
  mutate(Cost = TotalC / 1e6)

  # 6. Plot
  autoplot(a10, Cost) +
    labs(y = "$ (millions)",
         title = "Australian antidiabetic drug sales")

# Examine the dataset
a10
# A tsibble: 204 x 3 [1M]
      Month  TotalC  Cost
      <mth>   <dbl> <dbl>
 1 1991 Jul 3526591  3.53
 2 1991 Aug 3180891  3.18
 3 1991 Sep 3252221  3.25
 4 1991 Oct 3611003  3.61
 5 1991 Nov 3565869  3.57
 6 1991 Dec 4306371  4.31
 7 1992 Jan 5088335  5.09
 8 1992 Feb 2814520  2.81
 9 1992 Mar 2985811  2.99
10 1992 Apr 3204780  3.20
# ℹ 194 more rows

With this code we can obtain the components using X11 decomposition. We use this method because the series is multiplicative (more about that later in the chapter, do not worry too much about it now):

x11_dcmp <- 
  
  a10 %>%
  
  # 1. Define and fit the decomposition model
  model(x11 = X_13ARIMA_SEATS(Cost ~ x11())) %>%
  
  # 2. Extracts the components out of the model. Note that the function
  # components is not applicable to every type of model. It is applicable to
  # decomposition models and ETS models (later in the subject).
  components()

x11_dcmp
# A dable: 204 x 7 [1M]
# Key:     .model [1]
# :        Cost = trend * seasonal * irregular
   .model    Month  Cost trend seasonal irregular season_adjust
   <chr>     <mth> <dbl> <dbl>    <dbl>     <dbl>         <dbl>
 1 x11    1991 Jul  3.53  3.44    0.998     1.03           3.54
 2 x11    1991 Aug  3.18  3.42    0.988     0.941          3.22
 3 x11    1991 Sep  3.25  3.41    0.964     0.987          3.37
 4 x11    1991 Oct  3.61  3.41    1.06      0.999          3.41
 5 x11    1991 Nov  3.57  3.42    1.03      1.01           3.46
 6 x11    1991 Dec  4.31  3.45    1.29      0.971          3.35
 7 x11    1992 Jan  5.09  3.48    1.43      1.02           3.55
 8 x11    1992 Feb  2.81  3.52    0.799     1.00           3.52
 9 x11    1992 Mar  2.99  3.56    0.852     0.983          3.50
10 x11    1992 Apr  3.20  3.60    0.860     1.03           3.73
# ℹ 194 more rows

The following code overlays the trend component obtained by the decomposition on the original time-series

x11_dcmp %>%
  as_tsibble() %>%
  autoplot(Cost, colour="gray") +
  geom_line(aes(y=trend), colour = "#D55E00") +
  labs(
    y = "$ (millions)",
    title = "Australian antidiabetic drug sales"
  )

Again we can depict the components using autoplot:

x11_dcmp %>% autoplot()

Multiplicative scheme under different transformations

Most of the time multiplicative schemes can be made more “additive-like” with certain mathematical transformations. We will study these in a separate notebook, but let us examine them in a cursory manner here:

Let us look at the effect of applying different transformations of increasing strength to stabilize variations. The purpose is to turn the multiplicative scheme into an additive scheme.

Specifically we will apply a square root, a cubic root, a log and an inverse transformation:

a10 <- 
  a10 %>% 
  
  # Define different versions of the transformed variable
  mutate(
    sqrt_cost = sqrt(Cost),
    cbrt_cost = Cost^(1/3),
    log_cost = log(Cost),
    inv_cost = -1/Cost
    )
  
a10
# A tsibble: 204 x 7 [1M]
      Month  TotalC  Cost sqrt_cost cbrt_cost log_cost inv_cost
      <mth>   <dbl> <dbl>     <dbl>     <dbl>    <dbl>    <dbl>
 1 1991 Jul 3526591  3.53      1.88      1.52     1.26   -0.284
 2 1991 Aug 3180891  3.18      1.78      1.47     1.16   -0.314
 3 1991 Sep 3252221  3.25      1.80      1.48     1.18   -0.307
 4 1991 Oct 3611003  3.61      1.90      1.53     1.28   -0.277
 5 1991 Nov 3565869  3.57      1.89      1.53     1.27   -0.280
 6 1991 Dec 4306371  4.31      2.08      1.63     1.46   -0.232
 7 1992 Jan 5088335  5.09      2.26      1.72     1.63   -0.197
 8 1992 Feb 2814520  2.81      1.68      1.41     1.03   -0.355
 9 1992 Mar 2985811  2.99      1.73      1.44     1.09   -0.335
10 1992 Apr 3204780  3.20      1.79      1.47     1.16   -0.312
# ℹ 194 more rows

Now let us explore the effect of each transformation on the data (please excuse the spaghetti code style, in a professional environment dedicated functions or at least a for loop should have been written to avoid code repetition, also known as spaghetti code):

square root transformation

dcmp <- a10 %>%
  model(stl = STL(sqrt_cost))
components(dcmp)
# A dable: 204 x 7 [1M]
# Key:     .model [1]
# :        sqrt_cost = trend + season_year + remainder
   .model    Month sqrt_cost trend season_year remainder season_adjust
   <chr>     <mth>     <dbl> <dbl>       <dbl>     <dbl>         <dbl>
 1 stl    1991 Jul      1.88  1.82     -0.0218    0.0826          1.90
 2 stl    1991 Aug      1.78  1.83     -0.0215   -0.0207          1.81
 3 stl    1991 Sep      1.80  1.83     -0.0154   -0.0155          1.82
 4 stl    1991 Oct      1.90  1.84      0.0332    0.0242          1.87
 5 stl    1991 Nov      1.89  1.85      0.0617   -0.0251          1.83
 6 stl    1991 Dec      2.08  1.86      0.334    -0.120           1.74
 7 stl    1992 Jan      2.26  1.87      0.372     0.0139          1.88
 8 stl    1992 Feb      1.68  1.88     -0.249     0.0470          1.93
 9 stl    1992 Mar      1.73  1.89     -0.148    -0.0124          1.88
10 stl    1992 Apr      1.79  1.90     -0.152     0.0439          1.94
# ℹ 194 more rows
components(dcmp) %>%
  as_tsibble() %>%
  autoplot(sqrt_cost, colour="gray") +
  geom_line(aes(y=trend), colour = "#D55E00") +
  labs(
    y = "square root $ (millions)",
    title = "Australian antidiabetic drug sales"
  )

cubic root transformation

dcmp <- a10 %>%
  model(stl = STL(cbrt_cost))
components(dcmp)
# A dable: 204 x 7 [1M]
# Key:     .model [1]
# :        cbrt_cost = trend + season_year + remainder
   .model    Month cbrt_cost trend season_year remainder season_adjust
   <chr>     <mth>     <dbl> <dbl>       <dbl>     <dbl>         <dbl>
 1 stl    1991 Jul      1.52  1.49    -0.0100     0.0419          1.53
 2 stl    1991 Aug      1.47  1.49    -0.0103    -0.0135          1.48
 3 stl    1991 Sep      1.48  1.50    -0.00720   -0.0101          1.49
 4 stl    1991 Oct      1.53  1.50     0.0176     0.0134          1.52
 5 stl    1991 Nov      1.53  1.51     0.0323    -0.0124          1.50
 6 stl    1991 Dec      1.63  1.51     0.166     -0.0513          1.46
 7 stl    1992 Jan      1.72  1.52     0.185      0.0179          1.53
 8 stl    1992 Feb      1.41  1.52    -0.126      0.0161          1.54
 9 stl    1992 Mar      1.44  1.53    -0.0746    -0.0124          1.51
10 stl    1992 Apr      1.47  1.53    -0.0761     0.0186          1.55
# ℹ 194 more rows
components(dcmp) %>%
  as_tsibble() %>%
  autoplot(cbrt_cost, colour="gray") +
  geom_line(aes(y=trend), colour = "#D55E00") +
  labs(
    y = "cubic root $ (millions)",
    title = "Australian antidiabetic drug sales"
  )

logarithmic transformation

dcmp <- a10 %>%
  model(stl = STL(log_cost))
components(dcmp)
# A dable: 204 x 7 [1M]
# Key:     .model [1]
# :        log_cost = trend + season_year + remainder
   .model    Month log_cost trend season_year remainder season_adjust
   <chr>     <mth>    <dbl> <dbl>       <dbl>     <dbl>         <dbl>
 1 stl    1991 Jul     1.26  1.20     -0.0136  0.0736            1.27
 2 stl    1991 Aug     1.16  1.21     -0.0162 -0.0344            1.17
 3 stl    1991 Sep     1.18  1.22     -0.0105 -0.0255            1.19
 4 stl    1991 Oct     1.28  1.22      0.0332  0.0279            1.25
 5 stl    1991 Nov     1.27  1.23      0.0600 -0.0196            1.21
 6 stl    1991 Dec     1.46  1.24      0.278  -0.0567            1.18
 7 stl    1992 Jan     1.63  1.25      0.311   0.0684            1.32
 8 stl    1992 Feb     1.03  1.26     -0.221  -0.000911          1.26
 9 stl    1992 Mar     1.09  1.27     -0.128  -0.0439            1.22
10 stl    1992 Apr     1.16  1.27     -0.130   0.0195            1.29
# ℹ 194 more rows
components(dcmp) %>%
  as_tsibble() %>%
  autoplot(log_cost, colour="gray") +
  geom_line(aes(y=trend), colour = "#D55E00") +
  labs(
    y = "log root $ (millions)",
    title = "Australian antidiabetic drug sales"
  )

inverse transformation

dcmp <- a10 %>%
  model(stl = STL(inv_cost))
components(dcmp)
# A dable: 204 x 7 [1M]
# Key:     .model [1]
# :        inv_cost = trend + season_year + remainder
   .model    Month inv_cost  trend season_year remainder season_adjust
   <chr>     <mth>    <dbl>  <dbl>       <dbl>     <dbl>         <dbl>
 1 stl    1991 Jul   -0.284 -0.300  -0.0000614   0.0161         -0.283
 2 stl    1991 Aug   -0.314 -0.298  -0.00252    -0.0138         -0.312
 3 stl    1991 Sep   -0.307 -0.297  -0.000907   -0.00998        -0.307
 4 stl    1991 Oct   -0.277 -0.295   0.00852     0.00965        -0.285
 5 stl    1991 Nov   -0.280 -0.293   0.0144     -0.00149        -0.295
 6 stl    1991 Dec   -0.232 -0.292   0.0509      0.00844        -0.283
 7 stl    1992 Jan   -0.197 -0.290   0.0574      0.0359         -0.254
 8 stl    1992 Feb   -0.355 -0.288  -0.0464     -0.0213         -0.309
 9 stl    1992 Mar   -0.335 -0.285  -0.0253     -0.0242         -0.310
10 stl    1992 Apr   -0.312 -0.283  -0.0249     -0.00388        -0.287
# ℹ 194 more rows
components(dcmp) %>%
  as_tsibble() %>%
  autoplot(inv_cost, colour="gray") +
  geom_line(aes(y=trend), colour = "#D55E00") +
  labs(
    y = "Inverse cost $ (millions)",
    title = "Australian antidiabetic drug sales"
  )

Conclusion: strength of transformations

In conclusion, in terms of the strength of these transformations to turn a multiplicative scheme into an additive scheme, we can state the following x \[ \sqrt{x} < \sqrt[3]{x} < log(x) < \frac{1}{x} \]

Further visual examples of additive vs. multiplicative

The following image further clarifies the basic difference between an additive and a multiplicative time series. It has been borrowed from reference [2].

Multiplicative vs additive schemes. From reference [2].

In reference [2], there is an interesting interactive game where you can practice to recognize visual cues in additive and multiplicative schemes. I strongly encourage you to spend some minutes doing this.

Automating the identification of additive vs multiplicative schemes

Visual inspection is a first approach to assessing the scheme type and it is interesting for developing your intuition as analysts. However, when you are faced with batches of time series you need to process, it is definitely not the best approach. There are different ways in which the type of scheme could be evaluated.

One way of systematically assessing whether we should consider an additive or multiplicative scheme is to:

  1. Decompose the series using a method that is appropriate for additive schemes and a method appropriate for a multiplicative scheme.

  2. Assess the goodness of fit of each method. For example, assessing the amount of autocorrelation in the remainder of each decomposition.

Another possibility would be to:

  1. Fit an exponential smoothing with an additive scheme
  2. Fit an exponential smoothing with a multiplicative scheme.
  3. Compare their Akaike Information Criteria (\(AIC\) or \(AIC_c\)) to see which fits best

By the end of the course you should be able to understand all this completely.

Detrended and Seasonally Adjusted time series

Detrended time series

If \(T_t\) is the trend-cycle component of a time series, the detrended time series \(D_t\) is computed by removing the trend component from the time series.

This is done differently depending on whether the time series is additive or multiplicative

Additive scheme
\(y_t = T_t + S_t + R_t\)
Multiplicative scheme
\(y_t = T_t \cdot S_t \cdot R_t\)
\[D_t = y_t - T_t = S_t + R_t\] \[D_t = \frac{y_t}{T_t} = S_t \cdot R_t\]

Seasonally adjusted time series

If \(S_t\) is the seasonal component, the seasonally-adjusted time series \(A_t\) is computed by removing the seasonal component from the time series (hence seasonal adjusted series).

This is done differently depending on whether the time series is additive or multiplicative:

Additive scheme
\(y_t = T_t + S_t + R_t\)
Multiplicative scheme
\(y_t = T_t \cdot S_t \cdot R_t\)
\[A_t = y_t - S_t = T_t + R_t\] \[A_t = \frac{y_t}{S_t} = T_t \cdot R_t\]

It contains the remainder as well as the trend-cycle component. Therefore it is not “smooth”. Its short term fluctuations due to the remainder can be misleading when trying to predict a trend from it.

  • Technically, the slope of the tangent line to the curve (the derivative) changes abruptly every time-step due to these short term fluctuations. The trend is a smoother version with a smoother derivative and is therefore better to make an analysis of the overall direction of the time series.

  • If you want to look for turning poins and interpret changes in direction, it is best to use the trend cycle component rather than the seasonally adjusted data

The seasonally adjusted data is useful if the variation due to seasonality is not of primary interest.

  • Example: unemployment data are usually seasonally adjusted in order to highlight variation due to the underlying state of the economy rather than the seasonal variation

Example 1: additive scheme

Further up in this notebook we looked at the us_retail_employment time series and concluded it followed an additive scheme:

us_retail_employment %>% autoplot()
Plot variable not specified, automatically selected `.vars = Employed`

For this example we are going to fit a classical_decomoposition model. The specifics of this syntax will be explained in later sessions, but they are fairly straight forward.

classical_dcmp <- 
  us_retail_employment %>% 
  
  # 1. Fit the model
  model(
    dcmp = classical_decomposition(Employed, type = "additive")
  ) %>% 
  
  # 2. Extract the components
  components()

classical_dcmp
# A dable: 357 x 7 [1M]
# Key:     .model [1]
# :        Employed = trend + seasonal + random
   .model    Month Employed  trend seasonal random season_adjust
   <chr>     <mth>    <dbl>  <dbl>    <dbl>  <dbl>         <dbl>
 1 dcmp   1990 Jan   13256.    NA    -75.5   NA           13331.
 2 dcmp   1990 Feb   12966.    NA   -273.    NA           13239.
 3 dcmp   1990 Mar   12938.    NA   -253.    NA           13191.
 4 dcmp   1990 Apr   13012.    NA   -190.    NA           13203.
 5 dcmp   1990 May   13108.    NA    -88.9   NA           13197.
 6 dcmp   1990 Jun   13183.    NA    -10.4   NA           13193.
 7 dcmp   1990 Jul   13170. 13178.   -13.3    5.65        13183.
 8 dcmp   1990 Aug   13160. 13161.    -9.99   8.80        13169.
 9 dcmp   1990 Sep   13113. 13141.   -87.4   59.9         13201.
10 dcmp   1990 Oct   13185. 13117.    34.6   33.8         13151.
# ℹ 347 more rows

The resulting dataframe contains the following columns:

  • trend: trend component
  • seasonal: seasonal component
  • random: random component
  • season_adjust: seasonally adjusted component

Let us compute the detrended time series. Because the scheme is additive, we simply subtract the estimate of the trend from the original time series:

classical_dcmp <- 
  
  classical_dcmp %>% 
  
  # Compute new column containing the detrended component
  mutate(
    detrended = Employed - trend
  )

# Depict the result:
classical_dcmp %>% 
  autoplot(detrended)
Warning: Removed 12 rows containing missing values (`geom_line()`).

The detrended time series contains both the effect of the remainder and the seasonal component.

To compute the seasonally adjusted time series we simply remove the seasonal component from the time series. Since the scheme is additive, we attain this by subtraction. Note that the decomposition already provided a season_adjust column. We are going to compute it manually and then check that it leads to the same result:

classical_dcmp <- 
  
  classical_dcmp %>% 
  
  # Compute new column containing the detrended component
  mutate(
    season_adjust_manual = Employed - seasonal
  )

# Depict the result along with the original time series
classical_dcmp %>% 
  as_tsibble() %>% 
  autoplot(Employed, colour="gray") +
  geom_line(aes(y=season_adjust_manual), colour = "#D55E00") +
  labs(
    y = "Persons (thousands)",
    title = "Total employment in US retail"
  )

Note how the seasonally adjusted time series is different than the trend. It contains the trend plus the random component. You can recognize it in the short term fluctuations of the seasonally adjusted component. Compare it with the figure of trend, just below:

classical_dcmp %>% 
  as_tsibble() %>% 
  autoplot(Employed, colour="gray") +
  geom_line(aes(y=trend), colour = "#D55E00") +
  labs(
    y = "Persons (thousands)",
    title = "Total employment in US retail"
  )
Warning: Removed 12 rows containing missing values (`geom_line()`).

Comparing both, we see that the seasonally adjusted time series is not “smooth”. “Downturns” or “upturms” can be misleading. If you want to look for turning poins and interpret changes in direction, it is best to use the trend cycle component rather than the seasonally adjusted data

checking our manual computation with ´all.equal´

Finally, we can check that our manually generated seasonally adjusted series matches the seasonally adjusted series computed when using classical_decomposition(). The function all.equal compares two vectors element by element. It can be used as follows for the case at hand

all.equal(classical_dcmp$season_adjust, classical_dcmp$season_adjust_manual)
[1] TRUE

For the above code to evaluate to TRUE, sometimes you will require to round some of the components to a specific number of decimals for this to evaluate to true. This has to do with floating point inaccuracies etc… which you should have studied as part of computer science.

Example 2: multiplicative scheme

Further up in this notebook we have computed the dataset a10, corresponding to the expenses in anti-diabetic medications in Australia’s publich healthcare system. We concluded that this time series followed a multiplicative scheme:

a10 %>% 
  autoplot()
Plot variable not specified, automatically selected `.vars = TotalC`

For this example we are going to fit a classical_decomoposition model. The specifics of this syntax will be explained in later sessions, but they are fairly straight forward.

classical_dcmp <- 
  
  a10 %>% 
  
  # 1. Fit the model
  model(
    dcmp = classical_decomposition(Cost, type = "multiplicative")
  ) %>% 
  
  # 2. Extract the components
  components()

classical_dcmp
# A dable: 204 x 7 [1M]
# Key:     .model [1]
# :        Cost = trend * seasonal * random
   .model    Month  Cost trend seasonal random season_adjust
   <chr>     <mth> <dbl> <dbl>    <dbl>  <dbl>         <dbl>
 1 dcmp   1991 Jul  3.53 NA       0.979 NA              3.60
 2 dcmp   1991 Aug  3.18 NA       0.990 NA              3.21
 3 dcmp   1991 Sep  3.25 NA       0.986 NA              3.30
 4 dcmp   1991 Oct  3.61 NA       1.05  NA              3.45
 5 dcmp   1991 Nov  3.57 NA       1.08  NA              3.32
 6 dcmp   1991 Dec  4.31 NA       1.23  NA              3.50
 7 dcmp   1992 Jan  5.09  3.50    1.33   1.09           3.82
 8 dcmp   1992 Feb  2.81  3.53    0.780  1.02           3.61
 9 dcmp   1992 Mar  2.99  3.57    0.876  0.956          3.41
10 dcmp   1992 Apr  3.20  3.60    0.858  1.04           3.74
# ℹ 194 more rows

The resulting dataframe contains the following columns:

  • trend: trend component
  • seasonal: seasonal component
  • random: random component
  • season_adjust: seasonally adjusted component

To compute the de-trended time series, since this is a multiplicative scheme, we need to divide by the trend estimate:

classical_dcmp <- 
  
  classical_dcmp %>% 
  
  # Compute new column containing the detrended component
  mutate(
    detrended = Cost / trend
  )

# Depict the result:
classical_dcmp %>% 
  autoplot(detrended)
Warning: Removed 12 rows containing missing values (`geom_line()`).

The detrended component contains both the effect of the remainder and the seasonal component.

To compute the seasonally adjusted time series we simply remove the seasonal component from the time series. Since the scheme is multiplicative, we attain this by division. Note that the decomposition already provided a season_adjust column. We are going to compute it manually and then check that it leads to the same result:

classical_dcmp <- 
  
  classical_dcmp %>% 
  
  # Compute new column containing the detrended component
  mutate(
    season_adjust_manual = Cost / seasonal
  )

# Depict the result along with the original time series
classical_dcmp %>% 
  as_tsibble() %>% 
  autoplot(Cost, colour="gray") +
  geom_line(aes(y=season_adjust_manual), colour = "#D55E00")

Note how the seasonally adjusted component is different than the trend. It contains the trend plus the random component. You can recognize it in the short term fluctuations of the seasonally adjusted component. Compare it with the figure of trend, just below:

classical_dcmp %>% 
  as_tsibble() %>% 
  autoplot(Cost, colour="gray") +
  geom_line(aes(y=trend), colour = "#D55E00")
Warning: Removed 12 rows containing missing values (`geom_line()`).

checking our manual computation with ´all.equal´

Finally, we can check that our computation matches the seasonally adjusted compunent computed when using classical_decomposition() as follows:

all.equal(classical_dcmp$season_adjust, classical_dcmp$season_adjust_manual)
[1] TRUE

For the above code to evaluate to TRUE, sometimes you will require to round some of the components to a specific number of decimals for this to evaluate to true. This has to do with floating point inaccuracies etc… which you should have studied as part of computer science.

Mixed schemes

In many occasions schemes cannot be unequivocally classified as additive or multiplicative. We will deal with such cases when studying the box-cox transformation.

A common scheme that is not fully additive or multiplicative is a so called mixed scheme of the form:

\[\begin{align*} y_t = (S_t \times T_t ) + R_t \end{align*}\]
  • Trend-cycle and seasonality components relate in a multiplicative manner.
  • The remainder component is super-imposed in an additive scheme.

This particular scheme is relevant when:

  • The irregular component of the oscillations \(R_t\) does not grow with the level of the time series (and therefore is super-imposed in an additive manner)
  • The seasonal component grows with the level of the time series, and therefore is combined with the trend in a multiplicative manner.